<?php
/**
 * User: 假如_丶 <897645119@qq.com>
 * Date: 2020/5/9
 * Time: 14:08
 * 无可奈何花落去，似曾相识燕归来。
 */


namespace fanxd\repository\command\repository;

use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\Output;
use think\facade\App;
use think\facade\Config;
use think\console\input\Option;
use think\facade\Env;

class Create extends Command
{
    protected $type;

    protected function configure()
    {
        $this->setName('fanxd:repository')
            ->addArgument('name', Argument::OPTIONAL, "your name")
            ->addOption('api', null, Option::VALUE_NONE, 'Generate an api controller class.')
            ->setDescription('ThinkPHP 6 - Repositories to  the database layer');
    }

    protected function execute(Input $input, Output $output)
    {
        $name = trim($input->getArgument('name'));

        $path = substr($name,0,strpos($name, '/')) == '' ? 'admin' : substr($name,0,strpos($name, '/'));

        $className = $this->getClassName($name);

        foreach ($className as $key => $value) {
            $pathName = $this->getPathName($value);
            if (is_file($pathName)) {
                $output->writeln('<error>' . $pathName . ' already exists!</error>');
            } else {
                if (!is_dir(dirname($pathName))) {
                    mkdir(dirname($pathName), 0755, true);
                }
                file_put_contents($pathName, $this->buildClass($key, $value, $path));
                $output->writeln('<info>' . $this->type . $key .' created successfully.</info>');
            }
        }
    }

    protected function buildClass($stubName, $name, $path)
    {
        $stub = file_get_contents($this->getStub($stubName));

        $namespace = trim(implode('\\', array_slice(explode('\\', $name), 0, -1)), '\\');

        $class = str_replace($namespace . '\\', '', $name);

        $repositoryModel =  substr($class, 0, -10);

        return str_replace(['{%className%}', '{%namespace%}', '{%app_namespace%}', '{%repositoryModel%}', '{%app_path%}'], [
            $class,
            $namespace,
            App::getNamespace(),
            $repositoryModel,
            $path
        ], $stub);
    }

    protected function getPathName($name)
    {
        return Env::get('app_path') . ltrim(str_replace('\\', '/', $name), '/') . '.php';
    }

    protected function getClassName($name)
    {
        $appNamespace = App::getNamespace();

        if (strpos($name, $appNamespace . '\\') !== false) {
            return $name;
        }

        if (!Config::get('app_multi_module')) {
            if (strpos($name, '/')) {
                list($module, $name) = explode('/', $name, 2);
            } else {
                $module = 'admin';
            }
        } else {
            $module = null;
        }

        if (strpos($name, '/') !== false) {
            $name = str_replace('/', '\\', $name);
        }

        return [
            'controller' => $this->getNamespace($appNamespace, $module) . '\\' . 'controller\\' .$name.'Controller',
            'model' => $this->getNamespace($appNamespace, '') . '\\' . 'model\\' .$name,
            'repository' => $this->getNamespace($appNamespace, $module) . '\\' . 'repository\\' .$name.'Repository',
            //'validate' => $this->getNamespace($appNamespace, $module) . '\\' . 'validate\\' .$name.'Validate',
            'transform' => $this->getNamespace($appNamespace, $module) . '\\' . 'transform\\' .$name.'Transform'
        ];
    }

    protected function getNamespace($appNamespace, $module)
    {
        return $module ? ($appNamespace . '\\' . $module) : $appNamespace;
    }

    protected function getStub($stubName) {
        $stubPath = __DIR__  . '/../stubs' . DIRECTORY_SEPARATOR;
        return $stubPath . $stubName .'.stub';
    }
}